package com.rjj.tool;

import com.jfinal.plugin.activerecord.Record;
import org.apache.poi.hssf.usermodel.*;
import org.junit.Test;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

/**
 *excel测试工具
 * List<实体类> 有setter&&getter
 * 直接从数据库中导出数据
 *
 *
 * 导出数据，这里待修改的问题是
 * list遍历用了两次
 */
public class ExcelKit {


    //写入xls这个数据需要的实体类，直接用Java的反射机制动态调用既可以实现
    public static <T> void writeXls2(String fileName, Collection<T> map) {

        Map<String,Object> titleToVName = new HashMap<>();
        titleToVName.put("id","id");
        titleToVName.put("name","姓名");
        titleToVName.put("age","年龄");

        try {
            HSSFWorkbook wb = new HSSFWorkbook();
            //sheet的名字
            HSSFSheet sheet = wb.createSheet("sheetnum");
            Iterator<T> list = map.iterator();

            //表头名称写入
            // 产生表格标题行
            HSSFRow row = sheet.createRow(0);
            if (list.hasNext()) {
                //把数据拿到  就是泛型里边的数据
                T t = (T) list.next();
                // 利用反射，根据javabean属性的先后顺序，动态调用getXxx()方法得到属性值
                //拿到我们在实体类里边声明的变量
                Field[] fields = t.getClass().getDeclaredFields();

                HSSFRow finalRow = row;
                titleToVName.forEach((k, v) ->{
                    boolean isHaving = false;
                    for (int i = 0; i < fields.length; i++) {
                        Field field = fields[i];
                        //获取属性名称
                        String name = field.getName();
                        if(name.equals(k)){
                            HSSFCell cell = finalRow.createCell(i);
                            HSSFRichTextString text = new HSSFRichTextString((String) v);
                            cell.setCellValue(text);
                            isHaving = true;
                        }
                    }
                    if(isHaving){

                    }else {
                        throw  new RuntimeException("给出的表字段错误" + k + "->" + v);
                    }
                });
            }


            fixCentos(sheet, map,titleToVName);

            //输出到指定的位置
            FileOutputStream outputStream = new FileOutputStream(fileName);
            wb.write(outputStream);
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static <T> void fixCentos(HSSFSheet sheet,  Collection<T> map,Map<String,Object> titleToVName ) {
        Iterator<T> list = map.iterator();

        HSSFRow row;
        //HSSFRow row ;
        int index = 0;
        //下边是遍历设置Excel表格的行数数据
        while (list.hasNext())
        {
            System.out.println("list循环次数");
            //这个index++就是把第一行空出来了，最后添加表头
            index++;
            //创建行
            row = sheet.createRow(index);
            //把数据拿到  就是泛型里边的数据
            T t = (T) list.next();
            // 利用反射，根据javabean属性的先后顺序，动态调用getXxx()方法得到属性值
            //拿到我们在实体类里边声明的变量
            Field[] fields = t.getClass().getDeclaredFields();

            HSSFRow finalRow = row;
            titleToVName.forEach((k, v) ->{

                for (int i = 0; i < fields.length; i++)
                {
                    //拿到变量
                    Field field = fields[i];
                    String fieldName = field.getName();
                    if(fieldName.equals(k)){
                        System.out.println("相同字段数据" + fieldName + " ====" + k );
                        //组合成getxxx
                        String getMethodName = "get"
                                + fieldName.substring(0, 1).toUpperCase()
                                + fieldName.substring(1);

                        try
                        {
                            Class tCls = t.getClass();
                            //动态调用方法getxxx
                            Method getMethod = tCls.getMethod(getMethodName,
                                    new Class[]{});
                            Object value = getMethod.invoke(t, new Object[]{});
                            System.out.println("反射结果" + value);
                            // 判断值的类型后进行强制类型转换  ,这块我只写了三个基本的，是这个种数据类型就设置单元格的值
                            //创建列
                            HSSFCell cell = finalRow.createCell(i);
                            if (value instanceof Integer) {
                                int intValue = (Integer) value;
                                cell.setCellValue(intValue);
                            } else if (value instanceof Long) {
                                long longValue = (Long) value;
                                cell.setCellValue(longValue);
                            }else if (value instanceof String) {
                                String longValue = (String) value;
                                cell.setCellValue(longValue);
                            }
                        }catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                }
            });
        }
    }


    @Test
    public void testWrite12(){


        List<User> list = new ArrayList<>();
        User u = new User();
        u.setId(1);
        u.setName("sdfsd");
        u.setAge(12);
        list.add(u);

        User u1 = new User();
        u1.setId(12);
        u1.setName("sdeeefsd");
        u1.setAge(121);
        list.add(u1);

        list.stream().map(user -> user.name).forEach(System.out::println);

        writeXls2("/Users/renjianjun/study/ideaWorkSpace/wlqq/download/a1.xls", list);
    }

    private static class User {
        private int id;
        private String name;
        private int age;

        public void setId(int id) {
            this.id = id;
        }

        public int getId() {
            return id;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public int getAge() {
            return age;
        }
    }
}
